using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;
using System.Text;
using System.Data;
using ExceptionHandler;
using Microsoft.AnalysisServices.AdomdClient;
using System.Configuration;
using System.Globalization;
using System.Diagnostics;
using System.Threading;
using Microsoft.ApplicationBlocks.ExceptionManagement;


namespace ASUV
{
    #region Public sealed Class ProjectFile

	public sealed class ProjectFile
	{
		#region [members]
		private ProjectFile() { }
		static string location;
		static Thread lockFile;
		static FileStream fstream=null;
		#endregion

		#region public static string CreateProject(ProjectFileFoundEventArgs projectDetails)
		/// <summary>
        /// Create a xml project file with basic structure
        /// </summary>
        /// <param name="projectDetails">Contains basic details for creating the project file</param>
        /// <returns>Return string showing file created or exist in the specified location</returns>
        public static string CreateProject(ProjectFileFoundEventArgs projectDetails)
        {
           
			location=projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName;
			if (!File.Exists(projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName))
            {
				string projectName = projectDetails.ProjectName.Replace("&", "amp;");
				projectName = projectName.Replace("\"", "quot;");
				StringBuilder projectFile = new StringBuilder("<ProjectFile><ProjectName>" + projectDetails.ProjectName.Replace("&","amp;") + "</ProjectName><CreatedDateTime>"
                            + DateTime.Now.ToString() + "</CreatedDateTime><LastModifiedDateTime>" + DateTime.Now.ToString()
                            + "</LastModifiedDateTime><DatabaseName></DatabaseName><AS2K></AS2K><AS2K5></AS2K5><TotalQueries>0</TotalQueries>"
							+ "<QueriesPassed>0</QueriesPassed><QueriesFailed>0</QueriesFailed><MDXQueries></MDXQueries></ProjectFile>");
                StreamWriter streamWriter;
                streamWriter = File.CreateText(projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName);
                streamWriter.WriteLine(projectFile);
                streamWriter.Close();
				lockFile=new Thread(new ThreadStart(LockFile));
				lockFile.Start();
				return "File Created";
            }
            else return "File exist";
		}
		#endregion

		#region private static void LockFile()

		private static void LockFile()
		{

			fstream = new FileStream(location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
		}
		#endregion

		#region public static XmlDocument GetProjectDetails(string projectLocation)
		/// <summary>
        /// Retrive contents from file.
        /// </summary>
        /// <param name="projectLocation">Location of the Project opened</param>
        /// <returns>Returns xmldocument object that contains data in the project file</returns>
        public static XmlDocument GetProjectDetails(string projectLocation)
        {
			XmlDocument xmlDom = new XmlDocument();
			location = projectLocation;
			if (lockFile != null)
			{
				if (fstream != null)
				{
					fstream.Close();
				}
				lockFile.Abort();
			}
			try
			{
				xmlDom.Load(projectLocation);
				lockFile = new Thread(new ThreadStart(LockFile));
				lockFile.Start();
				return xmlDom;
			}
			catch (Exception ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error);
				return xmlDom;
			}
		}
		#endregion

		#region public static void SetProjectDetails(XmlDocument xmlDom, string projectLocation)
		/// <summary>
        /// This will save the modified and new contents to the project file
        /// </summary>
        /// <param name="xmlDom">Contains modified data to save the project file</param>
        /// <param name="projectLocation">Location of the Project opened</param>
		public static void SetProjectDetails(XmlDocument xmlDom, string projectLocation)
        {
			location = projectLocation;
			if (lockFile != null)
			{
				if (fstream != null)
				{
					fstream.Close();
				}
				lockFile.Abort();
			}
			try
			{
				xmlDom.Save(projectLocation);
				lockFile = new Thread(new ThreadStart(LockFile));
				lockFile.Start();
				return;
			}
			catch (Exception ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error);
			}
		}
		#endregion

	}
    #endregion

    #region Public Class QueryFile
    public sealed class QueryFile
	{
		#region [members]
		static string delimiterMdx = ConfigurationManager.AppSettings["MDXDelimiter"].ToString(CultureInfo.CurrentCulture);
		static string delimiterLog = ConfigurationManager.AppSettings["LogDelimiter"].ToString(CultureInfo.CurrentCulture);
		#endregion

		#region [support code form 'ImportQuery()']
		#region static private string loadASCI( string sPath )
		/// <summary>
		/// returns a asci file from a give path
		/// </summary>
		/// <param name="sPath">path to file</param>
		/// <returns>read in file as string</returns>
		private static string loadASCI( string sPath )
		{
			StreamReader streamReader = File.OpenText(sPath);
			return streamReader.ReadToEnd();
		}
		#endregion

		#region static private string loadUNICODE(string sPath)
		/// <summary>
		/// reads in and loads a UNICODE file based on a given path.
		/// </summary>
		/// <param name="sPath">path to file</param>
		/// <returns>unicode file read into a string.</returns>
		private static string loadUNICODE(string sPath)
		{
			return File.ReadAllText(sPath, Encoding.Unicode);
		}
		#endregion

		#region private static string presentQuery(string sQuery)
		/// <summary>
		/// takes a given string block and assumes the query starts with the first instance of a valid MDX SQL key word.
		/// </summary>
		/// <param name="sQuery">input text block with a query.</param>
		/// <returns>query removed from input string</returns>
		private static string presentQuery(string sQuery)
		{
			int iFirstWith = sQuery.ToLower(CultureInfo.CurrentCulture).IndexOf( "with" );
			int iFirstSelect = sQuery.ToLower(CultureInfo.CurrentCulture).IndexOf( "select" );
			sQuery = sQuery.Replace("^", "\"\"" );
			if (iFirstWith < 0 && iFirstSelect < 0) {
				return "";
			} 
			else if (iFirstWith < iFirstSelect && iFirstWith != -1 ) 
			{
				return sQuery.Substring(iFirstWith).Trim();
			}
			else
			{
				return sQuery.Substring(iFirstSelect).Trim();
			}
		}
		#endregion 
		#endregion

		#region private QueryFile() { }
		private QueryFile() { }
		#endregion

		#region public static string[] ImportQuery(string location)
		/// <summary>
        /// Retrive queries from supplied file and split each query and stored into array of string.
        /// </summary>
        /// <param name="location">Contains location of file</param>
        /// <returns>Returns array of string contain queries</returns>
		
        public static string[] ImportQuery(string location)
		{
			StringBuilder sbOutput			= new StringBuilder();
			char cDelimiter					= ' ';
			try
			{
				string sFileType = location.Substring(location.LastIndexOf('.') + 1);
				string sFile = string.Empty;
				string[] aFile;
				int iLength;

				switch (sFileType.ToLower(CultureInfo.CurrentCulture))
				{
					case "log":
						sFile = loadUNICODE(location);
						sFile = sFile.Replace("\t" + delimiterLog, "~").Replace("\r\n\r\n", "~");
						sFile = sFile.Replace("\r\n", "~");
						char[] acTemp = new char[] { '~' };
						aFile = sFile.Split(acTemp, StringSplitOptions.RemoveEmptyEntries);
						iLength = aFile.Length;
						break;
					default: //.mdx or .txt...
						sFile = loadASCI(location);
						char[] acTemp2;
						if (delimiterMdx.ToLower(CultureInfo.CurrentCulture) == "quote;")
						{
							acTemp2 = new char[] { '"' };
						}
						else
						{
							acTemp2 = delimiterMdx.ToCharArray();
						}
						// Deal with "" escape 
						sFile = sFile.Replace("\"\"", "^");
						// block queryies
						aFile = sFile.Split(acTemp2, StringSplitOptions.RemoveEmptyEntries);
						iLength = aFile.Length;
						break;
				}
				//clean 
				sFile = sFile.Replace("\r\n", " ");
				for (int x = 0; x < iLength; x++)
				{
					string sTemp = presentQuery(aFile[x]);
					if (sTemp.Length > 0)
					{
						sbOutput.Append(cDelimiter + sTemp);
						cDelimiter = '~';
					}
				}
			}
			catch (Exception ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error);
			}
			return sbOutput.ToString().Split(cDelimiter);
		}
		#endregion
	}
    #endregion

    #region Public Class AnalysisService
    public class AnalysisService
    {
		AdomdConnection kpiConnection;

		#region public bool TestConnection(string asInstance, string databaseName)
		/// <summary>
		/// Test the connection of 
		/// </summary>
		/// <param name="asInstance"></param>
		/// <param name="databaseName"></param>
		/// <returns></returns>
		public bool TestConnection(string asInstance, string databaseName)
		{
			string connectionString = "Data Source=" + asInstance.Replace("amp;", "&") + ";Catalog=\"" + databaseName.Replace("amp;", "&") + "\"";
			try
			{
				kpiConnection = new AdomdConnection(connectionString);
				kpiConnection.Open();
				kpiConnection.Close();
				return true;
			}
			catch (AdomdConnectionException ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error);
				return false;
			}
			catch (ArgumentException ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error);
				return false;
			}
			catch (Exception ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool",ex.ToString(),EventLogEntryType.Error);
				return false;
			}
		}
		#endregion

		#region public string[] GenerateQuery(string cubeName,int count,ProjectFileFoundEventArgs projectDetails)
		/// <summary>
		/// Dynamically generating queries corresponding to database and cube
		/// </summary>
		/// <param name="cubeName">Cube Name</param>
		/// <param name="count">Number of queries</param>
		/// <param name="projectDetails">project details</param>
		/// <returns></returns>
		public string[] GenerateQuery(string cubeName,int count,ProjectFileFoundEventArgs projectDetails)
		{
			string dataSource,catalog;
			CubeDef myCubeDef;
			bool connectionStatus=false;
			StringBuilder stringBuilderDimensions=new StringBuilder();
			StringBuilder stringBuilderCardinality=new StringBuilder();
			string[] stringArrQuery;
			string stringEmpty = "|";
			XmlDocument xmlDomProjectContent = ProjectFile.GetProjectDetails(projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName);
			catalog = xmlDomProjectContent.SelectSingleNode("ProjectFile/DatabaseName").InnerText;
			dataSource = xmlDomProjectContent.SelectSingleNode("ProjectFile/AS2K").InnerText;
			try
			{
				if (dataSource.Trim().Length == 0) throw new CustomAppException("customException13");
				if (catalog.Trim().Length == 0) throw new CustomAppException("customException15");
				string connectionString = "Data Source=" + dataSource.Replace("amp;", "&") + ";Catalog=\"" + catalog.Replace("amp;", "&") + "\"";
				kpiConnection = new AdomdConnection(connectionString);
				kpiConnection.Open();
				connectionStatus = true;
				myCubeDef = kpiConnection.Cubes[cubeName];

				//
				//Iterate through all dimensions, hierarchies and level and save all dimensions with herarchies and levels to array of string
				//
				for (int i = 0; i < myCubeDef.Dimensions.Count; i++)
					for (int j = 0; j < myCubeDef.Dimensions[i].Hierarchies.Count; j++)
						for (int k = 0; k < myCubeDef.Dimensions[i].Hierarchies[j].Levels.Count; k++)
						{
							Level level = myCubeDef.Dimensions[i].Hierarchies[j].Levels[k];
							int cardinality = int.Parse(level.Properties["LEVEL_CARDINALITY"].Value.ToString(), CultureInfo.CurrentCulture);
							if (cardinality >=1 && cardinality < 25)
							{
								stringBuilderDimensions.Append("|" + level.UniqueName);
								stringBuilderCardinality.Append("|" + level.Properties["LEVEL_CARDINALITY"].Value.ToString());
							}
						}
				string[] stringArrDimensions = stringBuilderDimensions.ToString().Split('|');
				string[] stringArrCardinality = stringBuilderCardinality.ToString().Split('|');
				StringBuilder stringBuilderQueries = new StringBuilder();
				char[] splitter = { '.' };
				int counter = 0;
				//
				//Generating Query using one dimension
				//
				for (int i = 1; i < stringArrDimensions.Length && counter < count; i++)
				{
					int cellCount = int.Parse(stringArrCardinality[i], CultureInfo.CurrentCulture);
					if (cellCount >= 1 && cellCount < 1000)
					{
						string[] stringTemp1 = stringArrDimensions[i].Split(splitter);
						if (stringTemp1[0] != "[Measures]")
						{
							string stringTemp = "SELECT measures.members ON 0, {" + stringArrDimensions[i] + ".members} ON 1 FROM [" + cubeName + "]";
							//
							//Check whether generated query already exist in the project file or not
							//
							if (xmlDomProjectContent.SelectSingleNode("ProjectFile/MDXQueries/MDXQuery[QueryAS2K=\"" + stringTemp + "\"]") == null)
							{
								stringBuilderQueries.Append("|SELECT measures.members ON 0, {" + stringArrDimensions[i] + ".members} ON 1 FROM [" + cubeName + "]");
								counter++;
							}
						}
					}
				}

				//
				//Generating Query using two dimensions
				//
				for (int i = 1; i < stringArrDimensions.Length && counter < count; i++)
				{
					for (int j = i + 1; j < stringArrDimensions.Length && counter < count; j++)
					{
						int cellCount = int.Parse(stringArrCardinality[i], CultureInfo.CurrentCulture) * int.Parse(stringArrCardinality[j], CultureInfo.CurrentCulture);
						if (cellCount >=1 && cellCount < 1000)
						{

							string[] stringTemp1 = stringArrDimensions[i].Split(splitter);
							string[] stringTemp2 = stringArrDimensions[j].Split(splitter);
							if (stringTemp1[0] != "[Measures]" && stringTemp2[0] != "[Measures]")
							{
								if (stringTemp1[0] != stringTemp2[0])
								{
									string stringTemp = "SELECT measures.members ON 0, {" + stringArrDimensions[i] + ".members * " + stringArrDimensions[j] + ".members} ON 1 FROM [" + cubeName + "]";
									//
									//Check whether generated query already exist in the project file or not
									//
									if (xmlDomProjectContent.SelectSingleNode("ProjectFile/MDXQueries/MDXQuery[QueryAS2K=\"" + stringTemp + "\"]") == null)
									{
										stringBuilderQueries.Append("|SELECT measures.members ON 0, {" + stringArrDimensions[i] + ".members * " + stringArrDimensions[j] + ".members} ON 1 FROM [" + cubeName + "]");
										counter++;
									}
								}
							}
						}
					}
				}
				//
				//Generating Query using three dimensions
				//
				for (int i = 1; i < stringArrDimensions.Length && counter < count; i++)
				{
					for (int j = i + 1; j < stringArrDimensions.Length && counter < count; j++)
					{
						for (int k = j + 1; k < stringArrDimensions.Length && counter < count; k++)
						{
							int cellCount = int.Parse(stringArrCardinality[i], CultureInfo.CurrentCulture) * int.Parse(stringArrCardinality[j], CultureInfo.CurrentCulture) * int.Parse(stringArrCardinality[i], CultureInfo.CurrentCulture);
							if (cellCount >=1 && cellCount < 1000)
							{
								string[] stringTemp1 = stringArrDimensions[i].Split(splitter);
								string[] stringTemp2 = stringArrDimensions[j].Split(splitter);
								string[] stringTemp3 = stringArrDimensions[k].Split(splitter);
								if (stringTemp1[0] != "[Measures]" && stringTemp2[0] != "[Measures]" && stringTemp3[0] != "[Measures]")
								{
									if (stringTemp1[0] != stringTemp2[0] && stringTemp2[0] != stringTemp3[0])
									{
										string stringTemp = "SELECT measures.members ON 0, {" + stringArrDimensions[i] + ".members * " + stringArrDimensions[j] + ".members * " + stringArrDimensions[k] + ".members} ON 1 FROM [" + cubeName + "]";
										//
										//Check whether generated query already exist in the project file or not
										//
										if (xmlDomProjectContent.SelectSingleNode("ProjectFile/MDXQueries/MDXQuery[QueryAS2K=\"" + stringTemp + "\"]") == null)
										{
											stringBuilderQueries.Append("|SELECT measures.members ON 0, {" + stringArrDimensions[i] + ".members * " + stringArrDimensions[j] + ".members * " + stringArrDimensions[k] + ".members} ON 1 FROM [" + cubeName + "]");
											counter++;
										}
									}
								}

							}
						}
					}
				}
				stringArrQuery = stringBuilderQueries.ToString().Split('|');
				kpiConnection.Close();
			}
			catch (CustomAppException ex)
			{
				stringArrQuery = stringEmpty.Split('|');
				ExceptionManager.Publish(ex);
			}
			catch (AdomdConnectionException)
			{
				try
				{
					CustomPublisherException ex = new CustomPublisherException("Analysis Services 2000 Instance");
					throw new CustomAppException("customException17", ex);
				}
				catch (CustomAppException ex)
				{
					stringArrQuery = stringEmpty.Split('|');
					ExceptionManager.Publish(ex);
				}
			}
			catch (ArgumentException)
			{
				try
				{
					if (connectionStatus)
					{
						throw new CustomAppException("customException16");
					}
					else
					{
						CustomPublisherException ex = new CustomPublisherException("Analysis Services 2000 Instance");
						throw new CustomAppException("customException17", ex);
					}
				}
				catch (CustomAppException ex)
				{
					stringArrQuery = stringEmpty.Split('|');
					if (!connectionStatus)
					{
						stringArrQuery[1] = "VALID";
					}
					ExceptionManager.Publish(ex);
				}
			}
			catch (AdomdErrorResponseException)
			{
				try
				{
					throw new CustomAppException("customException29");
				}
				catch (CustomAppException ex)
				{
					stringArrQuery = stringEmpty.Split('|');
					ExceptionManager.Publish(ex);
				}
			}
			catch (Exception ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error);
				stringArrQuery = stringEmpty.Split('|');
			}
			return stringArrQuery;

		}
		#endregion

		#region public void ExecuteQueries(string asInstance,ProjectFileFoundEventArgs projectDetails)
		/// <summary>
		/// Execute all queries under the project agains the selected instance and save the result to project file
		/// </summary>
		/// <param name="asInstance">Analysis Service Instance</param>
		/// <param name="projectDetails">Project Details</param>
		public void ExecuteQueries(string asInstance,ProjectFileFoundEventArgs projectDetails)
		{

			string dataSource,catalog;
			string commandText;
			DateTime startTime, endTime;
			double executionTime; 
			XmlDocument xmlDomProjectContent = ProjectFile.GetProjectDetails(projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName);
			try
			{
				if (asInstance == "AS2K")
				{
					dataSource = xmlDomProjectContent.SelectSingleNode("ProjectFile/AS2K").InnerText;
					if (dataSource.Trim().Length == 0) throw new CustomAppException("customException13");
				}
				else
				{

					dataSource = xmlDomProjectContent.SelectSingleNode("ProjectFile/AS2K5").InnerText;
					if (dataSource.Trim().Length == 0) throw new CustomAppException("customException14");
				}
				catalog = xmlDomProjectContent.SelectSingleNode("ProjectFile/DatabaseName").InnerText;
				if (catalog.Trim().Length == 0) throw new CustomAppException("customException15");
				string connectionString = "Data Source=" + dataSource + ";Catalog=\"" + catalog + "\"";
				kpiConnection = new AdomdConnection(connectionString);
				kpiConnection.Open();
				AdomdCommand kpiCommand;
				XmlNode temp = xmlDomProjectContent.SelectSingleNode("ProjectFile/MDXQueries");
				int qryCount = 0;

				foreach (XmlNode xmlNodeQueries in xmlDomProjectContent.SelectSingleNode("ProjectFile/MDXQueries"))
				{
					qryCount = qryCount + 1;
					if (asInstance == "AS2K")
					{
						commandText = xmlNodeQueries.SelectSingleNode("QueryAS2K").InnerText.Replace("amp;", "&");
					}
					else
					{
						commandText = xmlNodeQueries.SelectSingleNode("QueryAS2K5").InnerText.Replace("amp;", "&");
					}
					commandText = commandText.Replace("lt;", "<");
					commandText = commandText.Replace("gt;", ">");
					commandText = commandText.Replace("quote;", "\"");
					try
					{
						kpiCommand = new AdomdCommand(commandText, kpiConnection);
						startTime = DateTime.Now;
						CellSet cs = kpiCommand.ExecuteCellSet();

						DataSet dsResult = new DataSet();
						dsResult.Locale = CultureInfo.InvariantCulture;
						dsResult.Tables.Add(GetDataTable(cs));
						dsResult.Tables[0].DataSet.DataSetName = "Results";
						dsResult.Tables[0].TableName = "Result";

						string str = dsResult.GetXml().Replace("_x0020_", "");
						endTime = DateTime.Now;
						executionTime = (endTime.Millisecond - startTime.Millisecond);
						if (executionTime < 0) executionTime = 0;
						if (asInstance == "AS2K")
						{
							xmlNodeQueries.SelectSingleNode("AS2KResult").InnerText = str;
							xmlNodeQueries.SelectSingleNode("AS2KExecDuration").InnerText = executionTime.ToString(CultureInfo.CurrentCulture);
							xmlNodeQueries.SelectSingleNode("AS2KQueryStatus").InnerText = "Execution Succeeded";
						}
						else
						{
							xmlNodeQueries.SelectSingleNode("AS2K5Result").InnerText = str;
							xmlNodeQueries.SelectSingleNode("AS2K5ExecDuration").InnerText = executionTime.ToString(CultureInfo.CurrentCulture);
							xmlNodeQueries.SelectSingleNode("AS2K5QueryStatus").InnerText = "Execution Succeeded";
						}

					}
					catch (AdomdErrorResponseException)
					{
						if (asInstance == "AS2K")
						{
							xmlNodeQueries.SelectSingleNode("AS2KResult").InnerText = "<Results>No Result</Results>";
							xmlNodeQueries.SelectSingleNode("AS2KExecDuration").InnerText = "";
							xmlNodeQueries.SelectSingleNode("AS2KQueryStatus").InnerText = "Execution Failed";
						}
						else
						{
							xmlNodeQueries.SelectSingleNode("AS2K5Result").InnerText = "<Results>No Result</Results>";
							xmlNodeQueries.SelectSingleNode("AS2K5ExecDuration").InnerText = "";
							xmlNodeQueries.SelectSingleNode("AS2K5QueryStatus").InnerText = "Execution Failed";
						}
					}
					catch (AdomdUnknownResponseException)
					{
						if (asInstance == "AS2K")
						{
							xmlNodeQueries.SelectSingleNode("AS2KResult").InnerText = "<Results>No Result</Results>";
							xmlNodeQueries.SelectSingleNode("AS2KExecDuration").InnerText = "";
							xmlNodeQueries.SelectSingleNode("AS2KQueryStatus").InnerText = "Execution Failed";
						}
						else
						{
							xmlNodeQueries.SelectSingleNode("AS2K5Result").InnerText = "<Results>No Result</Results>";
							xmlNodeQueries.SelectSingleNode("AS2K5ExecDuration").InnerText = "";
							xmlNodeQueries.SelectSingleNode("AS2K5QueryStatus").InnerText = "Execution Failed";
						}
					}
				}
				ProjectFile.SetProjectDetails(xmlDomProjectContent, projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName);
				kpiConnection.Close();
			}
			catch (AdomdConnectionException)
			{
				try
				{
					throw new CustomAppException("customException17");
				}
				catch (CustomAppException ex)
				{
					ExceptionManager.Publish(ex);
				}
			}
			catch (ArgumentException)
			{
				try
				{
					throw new CustomAppException("customException17");
				}
				catch (CustomAppException ex)
				{
					ExceptionManager.Publish(ex);
				}
			}
			catch (CustomAppException ex)
			{
				ExceptionManager.Publish(ex);
			}
			catch (Exception ex)
			{
				EventLog.WriteEntry("AS Upgrade Verification Tool", ex.ToString(), EventLogEntryType.Error); 
			}
		}
		#endregion

		#region private static DataTable GetDataTable(CellSet cs)
		/// <summary>
		/// Extract all data from CellSet to DataTable
		/// </summary>
		/// <param name="cs">CellSet</param>
		/// <returns>DataTable</returns>

		private static DataTable GetDataTable(CellSet cs)
		{		
			// design the datatable
			DataTable dt = new DataTable();
			dt.Locale = CultureInfo.InvariantCulture;
			DataColumn dc;
			DataRow dr;
			// add the columns
			dt.Columns.Add(new DataColumn("Description"));
			// first column
			// get the other columns from axis
			//Position p;
			string name;
			//Member m;
			if (cs.Axes.Count > 1 && cs.Cells.Count>0)
			{
				foreach (Position p in cs.Axes[0].Positions)
				{
					dc = new DataColumn();
					name = "";
					foreach (Member m in p.Members)
					{
						name = (name + (m.Caption + " "));
					}
					dc.ColumnName = name;
					dt.Columns.Add(dc);
				}
				// add each row, row label first, then data cells
				int y;
				//Position py;
				y = 0;
				if (cs.Axes.Count > 1)
					foreach (Position py in cs.Axes[1].Positions)
					{
						dr = dt.NewRow();
						// create new row
						//  Do the row label
						name = "";
						foreach (Member m in py.Members)
						{
							name = (name + (m.Caption));
						}
						dr[0] = name;
						// first cell in the row
						//  Data cells
						int x;
						for (x = 0; (x <= (cs.Axes[0].Positions.Count - 1)); x++)
						{
							if (cs[x, y].FormattedValue.ToString().Trim().Length != 0)
								dr[(x + 1)] = cs[x, y].FormattedValue;
							else
								dr[(x + 1)] = "[null]";
							// other cells in the row
						}
						dt.Rows.Add(dr);
						// add the row
						y = (y + 1);
					}
			}
			else
			{
				if (cs.Axes.Count == 0)
				{
					dc = new DataColumn();
					dc.ColumnName = "Data";
					dt.Columns.Add(dc);
					dr = dt.NewRow();
					for (int x = 0; (x <= (cs.Cells.Count - 1)); x++)
					{
					if (cs.Cells[x].FormattedValue.ToString().Trim().Length != 0)
						dr[x+1] = cs.Cells[x].FormattedValue;
					else
						dr[x+1] = "[null]";
					}
					dt.Rows.Add(dr);
				}
				else if (cs.Cells.Count > 1)
				{
					foreach (Position p in cs.Axes[0].Positions)
					{
						dc = new DataColumn();
						name = "";
						foreach (Member m in p.Members)
						{
							name = (name + (m.Caption + " "));
						}
						dc.ColumnName = name;
						dt.Columns.Add(dc);
					}
					dr = dt.NewRow();
					for (int x = 0; (x <= (cs.Axes[0].Positions.Count - 1)); x++)
					{
						if (cs.Cells[0].FormattedValue.ToString().Trim().Length != 0)
							dr[x + 1] = cs.Cells[x].FormattedValue;
						else
							dr[x + 1] = "[null]";
					}
					dt.Rows.Add(dr);
				}
				else
				{
					dc = new DataColumn();
					dc.ColumnName = "null";
					dt.Columns.Add(dc);
					dr = dt.NewRow();
					dr[1] = "null";
					dt.Rows.Add(dr);
				}
			}
			return dt;
		}
		#endregion

		#region public static void CompareQuery(ProjectFileFoundEventArgs projectDetails)
		/// <summary>
		/// Compare all the query resluts and save the comparison result to project file
		/// </summary>
		/// <param name="projectDetails">Project Details</param>
		public static void CompareQuery(ProjectFileFoundEventArgs projectDetails)
		{
			XmlDocument xmlDomProjectContent = ProjectFile.GetProjectDetails(projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName);
			int queriesPassed = 0;
			int queriesFailed = 0;

			foreach (XmlNode xmlNodeQuery in xmlDomProjectContent.SelectSingleNode("ProjectFile/MDXQueries"))
			{
				string as2kStatus=xmlNodeQuery.SelectSingleNode("AS2KQueryStatus").InnerText.Trim();
				string as2k5Status=xmlNodeQuery.SelectSingleNode("AS2K5QueryStatus").InnerText.Trim();
				if (as2kStatus != "Query not Executed" && as2k5Status != "Query not Executed")
				{
					string as2K = xmlNodeQuery.SelectSingleNode("AS2KResult").InnerText;
					string as2K5 = xmlNodeQuery.SelectSingleNode("AS2K5Result").InnerText;
					if (as2K == as2K5)
					{
						xmlNodeQuery.SelectSingleNode("ComparisonResult").InnerText = "Same Result";
						queriesPassed++;
					}
					else
					{
						as2K = as2K.Replace("&gt;", "!");
						as2K = as2K.Replace("&lt;", "!");
						string[] arrayas2K = as2K.Split('!');
						as2K5 = as2K5.Replace("&lt;", "!");
						as2K5 = as2K5.Replace("&gt;", "!");
						string[] arrayas2K5 = as2K5.Split('!');
						int err = 0;
						for (int i = 0; i < arrayas2K.Length; i++)
						{
							if (arrayas2K[i] != arrayas2K5[i])
							{
								err++;
							}
						}
						if (as2K.Length < as2K5.Length)
						{
							err += as2K5.Length - as2K.Length;
						}
						else
						{
							err += as2K.Length - as2K5.Length;
						}
						if (err > 1)
							xmlNodeQuery.SelectSingleNode("ComparisonResult").InnerText = err.ToString(CultureInfo.CurrentCulture) + " " + "Errors";
						else
							xmlNodeQuery.SelectSingleNode("ComparisonResult").InnerText = err.ToString(CultureInfo.CurrentCulture) + " " + "Error";
						queriesFailed++;

					}
				}
			}
			xmlDomProjectContent.SelectSingleNode("ProjectFile/QueriesPassed").InnerText=queriesPassed.ToString(CultureInfo.CurrentCulture);
			xmlDomProjectContent.SelectSingleNode("ProjectFile/QueriesFailed").InnerText = queriesFailed.ToString(CultureInfo.CurrentCulture);
			ProjectFile.SetProjectDetails(xmlDomProjectContent, projectDetails.ProjectLocation + "\\" + projectDetails.ProjectFileName);
		}
		#endregion
	}
    #endregion
}
